package com.bijava.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author bishichu
 * @description 日志工具类
 * @since 2021/11/21
 */
public class LoggerHelper {
    private LoggerHelper() {

    }

    private static final String TEMPLATE = "[%s.%s:%s] ==> ";

    /**
     * 获得日志，自动判定日志发出者
     * @return
     */
    private static Logger logger() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        String className = stackTrace[3].getClassName();
        return LoggerFactory.getLogger(className);
    }

    /**
     * 获取类名、方法名称，组装模板
     * @return
     */
    private static String template() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        String className = stackTrace[3].getClassName();
        String methodName = stackTrace[3].getMethodName();
        int lineNumber = stackTrace[3].getLineNumber();

        return String.format(TEMPLATE, className, methodName, lineNumber);
    }

    /**
     * 格式化文本
     * @param template 文本模板，被替换的部分用 {} 表示
     * @param values 参数值
     * @return 格式化后的文本
     */
    private static String format(String template, Object... values) {
        return String.format(template.replace("{}", "%s"), values);
    }

    /**
     * Trace等级日志，小于Debug
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void trace(String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = builder.toString();
        logger().trace(message, arguments);
    }

    /**
     * Debug等级日志，小于Info
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void debug(String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = builder.toString();
        logger().debug(message, arguments);
    }

    /**
     * Info等级日志，小于Warn
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void info(String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = builder.toString();
        logger().info(message, arguments);
    }

    /**
     * Warn等级日志，小于Error
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void warn(String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = builder.toString();
        logger().warn(message, arguments);
    }

    /**
     * Warn等级日志，小于Error
     * @param e 需在日志中堆栈打印的异常
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void warn(Throwable e, String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = format(builder.toString(),arguments);
        logger().warn(message, e);
    }

    /**
     * Error等级日志<br>
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void error(String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = builder.toString();
        logger().error(message, arguments);
    }

    /**
     * Error等级日志<br>
     * 由于动态获取Logger，效率较低，建议在非频繁调用的情况下使用！！
     * @param e 需在日志中堆栈打印的异常
     * @param format 格式文本，{} 代表变量
     * @param arguments 变量对应的参数
     */
    public static void error(Throwable e, String format, Object... arguments) {
        StringBuilder builder = new StringBuilder();
        builder.append(template()).append(format);
        String message = format(builder.toString(), arguments);
        logger().error(message, e);
    }

    /**
     * 是否开启debug
     * @return
     */
    public static Boolean isDebugEnabled() {
        return logger().isDebugEnabled();
    }
}
